﻿using System.Net.WebSockets;
using System.Threading.Tasks;
using System.Threading;
using System;
using System.Collections.Generic;

namespace WebAPIWebSockets
{
    /// <summary>
    /// WebSockets帮助类
    /// </summary>
    public static class WebSocketsHelper
    {
        /// <summary>
        /// 循环发送并反馈消息-未加密
        /// 逻辑：如果在开始循环之前接受 WebSocket 连接，中间件管道会结束。 关闭套接字后，管道展开。 即接受 WebSocket 时，请求停止在管道中推进。 循环结束且套接字关闭时，请求继续回到管道。
        /// </summary>
        /// <param name="webSocket">WebSocket对象</param>
        /// <returns></returns>
        public static async Task Echo(WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];
            var receiveResult = await webSocket.ReceiveAsync(  // 接收消息
                new ArraySegment<byte>(buffer), CancellationToken.None);

            while (!receiveResult.CloseStatus.HasValue)  // webSocket接收开启时，循环接收、转发
            {
                await webSocket.SendAsync(  // 转发消息
                    new ArraySegment<byte>(buffer, 0, receiveResult.Count),
                    receiveResult.MessageType,
                    receiveResult.EndOfMessage,
                    CancellationToken.None);

                receiveResult = await webSocket.ReceiveAsync(  // 接收消息
                    new ArraySegment<byte>(buffer), CancellationToken.None);
            }

            await webSocket.CloseAsync(  // 关闭WebSocket连接
                receiveResult.CloseStatus.Value,
                receiveResult.CloseStatusDescription,
                CancellationToken.None);
        }

        private static List<WebSocket> _webSockets = new List<WebSocket>();
        /// <summary>
        /// 循环发送和转发消息（聊天室）-未加密
        /// 逻辑：如果在开始循环之前接受 WebSocket 连接，中间件管道会结束。 关闭套接字后，管道展开。 即接受 WebSocket 时，请求停止在管道中推进。 循环结束且套接字关闭时，请求继续回到管道。
        /// </summary>
        /// <param name="webSocket">WebSocket对象</param>
        /// <returns></returns>
        public static async Task ChatRoom(WebSocket webSocket)
        {
            // 将webSocket加入到_webSockets
            if (!_webSockets.Contains(webSocket))
            {
                _webSockets.Add(webSocket);
            }

            var buffer = new byte[1024 * 4];
            var receiveResult = await webSocket.ReceiveAsync(  // 接收消息
                new ArraySegment<byte>(buffer), CancellationToken.None);

            while (!receiveResult.CloseStatus.HasValue)  // webSocket接收开启时，循环接收、转发
            {
                List<WebSocket> webSockets = new List<WebSocket>();

                foreach (WebSocket webSocket1 in _webSockets)
                {
                    if (webSocket1.State == WebSocketState.Open)
                    {
                        await webSocket1.SendAsync(  // 转发消息
                           new ArraySegment<byte>(buffer, 0, receiveResult.Count),
                           receiveResult.MessageType,
                           receiveResult.EndOfMessage,
                           CancellationToken.None);

                        webSockets.Add(webSocket1);
                    }
                }
                _webSockets= webSockets;

                receiveResult = await webSocket.ReceiveAsync(  // 接收消息
                    new ArraySegment<byte>(buffer), CancellationToken.None);
            }
            if (_webSockets.Count <= 0)
            {
                await webSocket.CloseAsync(  // 关闭WebSocket连接
                    receiveResult.CloseStatus.Value,
                    receiveResult.CloseStatusDescription,
                    CancellationToken.None);
            }
        }
    }
}
